package com.github.permissiondog.cancanpbackend.service;

import com.github.permissiondog.cancanpbackend.Database;
import com.github.permissiondog.cancanpbackend.dao.UserDao;
import com.github.permissiondog.cancanpbackend.model.Role;
import com.github.permissiondog.cancanpbackend.model.User;
import lombok.Getter;
import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.session.SqlSession;
import org.mindrot.jbcrypt.BCrypt;

import java.util.List;

public class UserService {
    private UserService() {

    }
    @Getter private static final UserService instance = new UserService();

    public User login(String username, String password) {
        try (SqlSession sqlSession = Database.getInstance().openSession()) {
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            User u = userDao.getUserByUsername(username);
            if (u == null) {
                return null;
            }
            //使用BCrypt库对密码进行加密和验证
            if (BCrypt.checkpw(password, u.getPassword())) {
                u.setPassword(null);
                return u;
            } else {
                return null;
            }
        }
    }

    public int createUser(String username, String nickname, String password, String department, Role role) {
        User u = new User();
        u.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
        u.setNickname(nickname);
        u.setUsername(username);
        u.setDepartment(department);
        u.setRole(role);
        try (SqlSession session = Database.getInstance().openSession()) {
            UserDao userDao = session.getMapper(UserDao.class);
            userDao.insertUser(u);
            return u.getId();
        }
    }

    public User getUserById(int uid) {
        try (SqlSession session = Database.getInstance().openSession()) {
            UserDao userDao = session.getMapper(UserDao.class);
            User u = userDao.getUserById(uid);
            if (u == null)  return null;
            u.setPassword(null);
            return u;
        }
    }
    public List<User> getUserByRole(Role role) {
        try (SqlSession session = Database.getInstance().openSession()) {
            UserDao userDao = session.getMapper(UserDao.class);
            var u = userDao.getUserByRole(role);
            u.forEach(user -> user.setPassword(null));
            return u;
        }
    }

    public List<User> getUsers() {
        try (var session = Database.getInstance().openSession()) {
            var userDao = session.getMapper(UserDao.class);
            return userDao.getUsers().stream().peek(u -> u.setPassword(null)).toList();
        }
    }

    //修改用户信息
    public void modifyUser(User user) {
        try (var session = Database.getInstance().openSession()) {
            var userDao = session.getMapper(UserDao.class);
            var oldUser = userDao.getUserById(user.getId());
            if (oldUser == null) {
                throw new RuntimeException("用户 ID 不存在");
            }
            user.setPassword(oldUser.getPassword());
            userDao.updateUser(user);
            user.setPassword(null);
        }
    }

    public void changePassword(int userId, String password) {
        try (var session = Database.getInstance().openSession()) {
            var userDao = session.getMapper(UserDao.class);
            var user = userDao.getUserById(userId);
            if (user == null) {
                throw new RuntimeException("用户 ID 不存在");
            }
            user.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
            userDao.updateUser(user);
        }
    }

    public void deleteUser(int userId) {
        try (var session = Database.getInstance().openSession()) {
            var userDao = session.getMapper(UserDao.class);
            var user = userDao.getUserById(userId);
            if (user == null) {
                throw new RuntimeException("用户 ID 不存在");
            }
            if ("admin".equals(user.getUsername())) {
                throw new RuntimeException("默认管理员无法删除");
            }
            userDao.deleteUser(userId);
        }
    }

    public User getUserByUsername(String username) {
        try (var session = Database.getInstance().openSession()) {
            var userDao = session.getMapper(UserDao.class);
            var user = userDao.getUserByUsername(username);
            if (user == null) {
                return null;
            }
            user.setPassword(null);
            return user;
        }
    }
}
